import os
import time
import uuid
import ast
from utilsapp import utils
from flask import current_app, request
from flask import (
    Blueprint,
    request,
    jsonify,
    current_app,
    send_from_directory,
    send_file,
    render_template,
)
from collections import defaultdict
from utilsapp.mysql_con import db_delete, db_insert, db_list
from utilsapp.mysql_con import (
    db_pagelist,
    db_fetchone,
    db_connect,
    db_deletes,
    db_fetchall,
)
from utilsapp.common import (
    assign_value,
    parsing_data_id,
    get_collection_name,
    parsing_permissions,
)
from datetime import datetime

report = Blueprint("report", __name__)


# 查询诊断报告
@report.route("/getlist", methods=["POST"])
def a():
    a = request.json
    scope_id = assign_value(a, "scope_id", 0)
    scoped = parsing_data_id(scope_id, request)
    title = assign_value(a, "title")
    maker = assign_value(a, "maker")
    start_time = assign_value(a, "start_time")
    end_time = assign_value(a, "end_time")
    status = assign_value(a, "status")
    type_ = assign_value(a, "type")
    query = ""
    if scoped != "":
        query += f" and {scoped}"
    if maker != "":
        query += f" and maker like '%{maker}%'"
    if title != "":
        query += f" and title like '%{title}%'"
    if start_time != "":
        query += f" and create_time > {start_time}"
    if end_time != "":
        query += f" and create_time < {end_time}"
    if status != "":
        query += f" and status = {status}"
    if type_ != "":
        query += f" and type = {type_}"
    elif type_ == "":
        query += f" and type != 3"
    sql = f"select * from report where 1=1 {query} ORDER BY create_time desc"

    sql_1 = f"select count(id) from report where 1=1 {query} and status="
    res = db_pagelist(sql, a["page"])
    res1 = db_fetchone(sql_1 + "1")
    res0 = db_fetchone(sql_1 + "0")
    res["stat"] = {"editing": res0["data"], "completed": res1["data"]}
    return res


@report.route("/upload", methods=["POST", "get"])
def upload():
    try:
        if "file" not in request.files:
            return jsonify({"code": -1, "msg": "空文件"}), 200
        dimg = request.args.get("dimg")
        file = request.files["file"]
        # 检查文件是否为空
        if file.filename == "":
            return jsonify({"code": -1, "msg": "空文件"}), 200
        script_dir = os.path.dirname(os.path.abspath(__name__)) + "/static"
        date = time.strftime("%Y%m%d", time.localtime())
        ext = os.path.splitext(file.filename)[-1]
        fileName = f"/upload/{date}"
        filePath = script_dir + fileName
        if not os.path.exists(filePath):
            # 递归创建文件夹
            os.makedirs(filePath)
        fileName = f"/upload/{date}/{uuid.uuid1()}{ext}"
        filePath = script_dir + fileName
        ALLOWED_EXTENSIONS = {"pdf", "png", "jpg", "jpeg", "gif", "txt"}
        if (
            "." in file.filename
            and file.filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
        ) == False:
            return jsonify({"code": -1, "msg": "上传失败,非法文件类型"}), 200
        if ext == ".pdf":
            filePath = script_dir + f"/upload/{file.filename}"
            fileName = file.filename
        if dimg == "1":
            filePath = script_dir + "/upload/dimg"
            if not os.path.exists(filePath):
                os.makedirs(filePath)
            filePath = filePath + "/" + file.filename
            fileName = "/upload/dimg/" + file.filename
        # 保存文件到指定目录
        print("上传路径", filePath, fileName)
        file.save(filePath)
        return jsonify({"code": 0, "msg": "上传成功", "data": fileName}), 200
    except Exception as e:
        return jsonify({"code": -1, "msg": "上传异常"}), 200


@report.route("/add", methods=["post"])
def add():
    return db_insert("report", request.json)


@report.route("/viewpdf/<path:filename>", methods=["POST", "GET"])
def view_file(filename):
    try:
        script_dir = os.path.dirname(os.path.abspath(__name__)) + "/static"
        filePath = script_dir + "/upload/" + filename
        print("下载路径", filePath)
        return send_file(filePath, mimetype="application/pdf")
    except Exception as e:

        return jsonify({"code": -1, "msg": "下载异常" + str(e)}), 200


@report.route("/download/<path:filename>", methods=["POST", "GET"])
def download_file(filename):
    try:
        script_dir = os.path.dirname(os.path.abspath(__file__))
        filePath = script_dir + "/upload/"

        return send_from_directory(filePath, filename, as_attachment=True)
    except Exception as e:
        return jsonify({"code": -1, "msg": "下载异常"}), 200


@report.route("delete", methods=["post"])
def report_delete():
    id_ = request.json["id"]
    return db_delete("report", f"where id = %s", {"mid": id_})


@report.route("deletes", methods=["post"])
def report_deletes():
    id_ = " or ".join([("id = " + str(item)) for item in request.json["idList"]])
    sql = f"DELETE FROM report where {id_}"
    return db_deletes(sql)


def convert_tuple(lst):
    if len(lst) == 1:
        return f"({lst[0]})"
    else:
        return tuple(lst)


def get_page1(device_ids, times, group_name):
    support = ""

    try:
        config = current_app.config["settings"]
        if "support" in config and len(config["support"]) > 0:
            support = config["support"]
    except:
        support = ""
    return {
        "title": "设备状态监测分析报告",
        "times": times,
        "project_name": group_name,
        "support": support,
        "reporter": "系统生成",
        "examine": "系统审核",
        "permiss": "系统批准",
        "create_time": datetime.now().strftime("%Y年%m月%d日"),
    }


def set_result(results, a):
    result_list = []
    for pair in a:
        i, j = pair
        if i != 0 and j != 0:
            result_list.append(results[i][j])
    if not result_list:
        result_list.append("正常")
    # 使用set去重，并转换为列表
    result_list = list(set(result_list))
    return ",".join(result_list)


def setList(input_str):
    if input_str == "[]":
        input_str = "[0, 0]"

    input_str = input_str.replace("[", "").replace("]", "").split(",")
    # 安全地解析输入字符串
    processed_lst = [0, 0]
    # 定义映射字典
    replacement_map = {
        "固定阈值": 1,
        "动态阈值": 2,
        "趋势预测": 3,
        "机理模型": 4,
        "AI模型": 5,
    }

    try:
        processed_lst[0] = int(input_str[0])
    except:
        processed_lst[0] = replacement_map[input_str[0]]
    processed_lst[1] = int(input_str[1])

    return [tuple(processed_lst)]


def get_page3s(device_ids, times, type_=0):
    page_len1 = 20
    stime = times[0]
    etime = times[1]
    titles = ["一、诊断总结，状态描述和维护建议", "一、报警设备状态"]
    results = [
        ["正常", "正常", "正常", "正常"],
        ["正常", "固定阈值轻微超限", "固定阈值中等超限", "固定阈值严重超限"],
        ["正常", "动态阈值轻微超限", "动态阈值中等超限", "动态阈值严重超限"],
        ["正常", "特征趋势轻微超限", "特征趋势中等超限", "特征趋势严重超限"],
        ["正常", "智能告警轻微告警", "智能告警中等告警", "智能告警严重告警"],
        ["正常", "机理告警轻微告警", "机理告警中等告警", "机理告警严重告警"],
    ]
    suggests = [
        "设备正常",
        "按计划维护，关注运行数据",
        "关注趋势，对比历史数据排查",
        "分析数据，现场检查，适时调整",
    ]
    status_ = ["正常", "一般告警", "中等告警", "严重告警"]
    sql2 = ""
    if type_ == 0:
        sql2 = f"""
        SELECT
    d.device_name,
    COALESCE(MAX(w.warn_level), 0) AS warn_level,
    IFNULL(GROUP_CONCAT(CONCAT('[', w.warn_source, ',', w.warn_level, ']')), '[]') AS result_list
FROM
    device d
LEFT JOIN (
    SELECT
        device_id,
        warn_source,
        MAX(warn_level) AS warn_level
    FROM
        warn
    WHERE
        is_show = 1 
        AND notice NOT IN (3,4) 
        AND pred_time BETWEEN '{stime}' AND '{etime}'
    GROUP BY
        device_id,
        warn_source
) w ON w.device_id = d.id
WHERE
    d.id IN {convert_tuple(device_ids)}
GROUP BY
    d.device_name;
        """
    elif type_ == 1:
        sql2 = f"""
SELECT 
    d.device_name,
    s.sensor_name,
    COALESCE(MAX(w.warn_level), 0) AS warn_level,
    IFNULL( GROUP_CONCAT(CONCAT('[', w.warn_source, ',', w.warn_level, ']')),'[0,0]') AS result_list
FROM 
    sensor s
JOIN 
    device d ON d.id = s.device_id
LEFT JOIN (
    SELECT 
        * 
    FROM 
        warn
    WHERE 
        is_show = 1 AND 
        notice NOT IN (3,4) and pred_time between '{stime}' and '{etime}'
) w ON w.sensor_id = s.id
WHERE 
    d.id = {device_ids[0]}
GROUP BY 
    d.device_name,
    s.sensor_name
ORDER BY 
    d.device_name,
    s.sensor_name,
    MAX(w.warn_level) DESC;
"""
    items = db_list(sql2)["data"]
    if type_ == 0:
        page3 = {
            "title": titles[type_],
            "list": [],
        }
        for index, item in enumerate(items):
            device_dict = {
                "device_name": item["device_name"],
                "status": status_[item["warn_level"]],
                "result": set_result(results, setList(item["result_list"])),
                "suggest": suggests[item["warn_level"]],
            }
            page3["list"].append(device_dict)
            # current_page = page3[-1]
            # current_page_list = current_page["list"]
            # current_page_list.append(device_dict)
            # if len(current_page_list) == page_len1 and index  < len(items)-1:
            #     new_page = {
            #         "title": titles[type_],
            #         "list": []
            #     }
            #     page3.append(new_page)
    elif type_ == 1:
        page3 = {
            "title": titles[type_],
            "list": [],
            "device_name": items[0]["device_name"],
        }
        for index, item in enumerate(items):
            device_dict = {
                "sensor_name": item["sensor_name"],
                "status": status_[item["warn_level"]],
                "result": set_result(results, setList(item["result_list"])),
                "suggest": suggests[item["warn_level"]],
            }
            page3["list"].append(device_dict)
            # current_page = page3[-1]
            # current_page_list = current_page["list"]
            # current_page_list.append(device_dict)
            # if len(current_page_list) == page_len1 and index  < len(items)-1:
            #     new_page = {
            #         "title": titles[type_],
            #         "list": [],
            #         "device_name":items[0]['device_name']
            #     }
            #     page3.append(new_page)
    return page3


def timesFor(date_string):
    date_format = "%Y-%m-%d %H:%M:%S"
    # 将日期时间字符串转换为 datetime 对象
    dt = datetime.strptime(date_string, date_format)
    # 获取对应的时间戳（10位）
    timestamp = int(dt.timestamp())
    return timestamp


def get_channel(address):
    parts = address.split("_")
    first_number = str(parts[0])
    second_number = str(parts[1]) if len(parts) > 1 else "0"
    return [first_number, second_number]


def dilute_list(lst):
    if len(lst) > 10000:
        ratio = len(lst) / 10000
        new_lst = [lst[int(i * ratio)] for i in range(10000)]
        return new_lst
    else:
        return lst


def get_page4s(device_ids, times, pagesize=4):
    page_len1 = pagesize
    stime = times[0]
    etime = times[1]
    warn_level_dir = ["正常", "一般告警", "中等告警", "严重告警"]
    sql1 = f"""SELECT s.sensor_name,IFNULL( MAX(w.warn_level),0) as warn_level,d.device_name,s.address,s.port,st.single,s.direction,
                r.proj_no
				from sensor s
				LEFT JOIN ( SELECT * from warn where is_show = 1 AND notice not in (3,4) and pred_time between '{stime}' and '{etime}' ) w on w.sensor_id = s.id
				LEFT JOIN device d on d.id = s.device_id
                left join sensor_type st on st.id = s.sensor_type
                LEFT JOIN regionlevel r on r.id = d.group_id
					where d.id in {convert_tuple(device_ids)}
				GROUP BY s.id"""
    items = db_list(sql1)["data"]
    page4 = {
        "title": "二、设备振动趋势分析",
        "list": [],
    }
    for index, item in enumerate(items):
        device_name = item["device_name"]
        sensor_name = item["sensor_name"]
        address = item["address"]
        port = item["port"]
        warn_level = item["warn_level"]
        sport = port
        arr = get_channel(address)
        saddr = arr[0]
        channel = arr[1]
        proj_no = item["proj_no"]
        mgdb = current_app.mgdb[f"ieplat_{proj_no}"]

        dbname1 = f"eige_{sport}_{saddr.split('_')[0]}"
        dbname = get_collection_name(mgdb,dbname1)
        query = {
            "$and": [
                {"_id": {"$gte": f"{sport}_{saddr}_{channel}_{timesFor(stime)}"}},
                {"_id": {"$lte": f"{sport}_{saddr}_{channel}_{timesFor(etime)}"}},
            ]
        }
        projection = {"_id": 1, **{f"data.{e}": 1 for e in ["Z.vel_rms", "Z.acc_rms"]}}
        collection = mgdb[dbname]
        result = collection.find(query, projection)
 
        d = [{"id": t["_id"][-10:], **t["data"]} for t in result]
        page4["list"].append(
            {
                "device_name": device_name,
                "sensor_name": sensor_name,
                "status": warn_level_dir[warn_level],
                "data": dilute_list(d),
                "number": f"{port}_{address}",
            }
        )

    return page4


def get_page2():
    return {
        "title": "注意事项",
        "list": [
            """
            1、本报告需委托方核实基本机组机械参数(如:机组传动链图、齿轮箱结构图、齿轮箱齿数等、相关的轴承型号及品牌)，有助于分析诊断的准确性；
""",
            """
2、本报告为专业技术人员对机组的分析和诊断、维护意见,仅供参考,具体维护维修措施还需委托方自行决定；
""",
            """
3、本报告不作为任何理赔、诉讼等证明材料;
""",
            """
4.委托方负有对分析报告保密的义务，未经受托方书面许可不得将本报告提供给第三方印刷成其它宣传材料或发布于网络等公共信息平台
""",
        ],
    }


@report.route("down/sys", methods=["post"])
def a23321():
    a = request.json
    device_ids = assign_value(a, "device_ids", [])
    times = assign_value(a, "times", [])
    type_ = assign_value(a, "type_", 0)
    sql = f"""select r.name from device d
        LEFT JOIN regionlevel r on r.id = d.group_id
        where d.id = {device_ids[0]} """
    times1 = [convert_date(times[0]), convert_date(times[1])]
    group_name = db_fetchone(sql)["data"]
    page1 = get_page1(device_ids, times1, group_name)
    page2 = get_page2()
    page3 = get_page3s(device_ids, times, type_)
    page4 = get_page4s(device_ids, times)

    if type_ == 0:
        return send_file(a[0], as_attachment=True, attachment_filename=a[1] + ".pdf")
    elif type_ == 1:
        # send_file(a[0], as_attachment=True, attachment_filename=a[1] + ".pdf")
        return save_warn_port(a[1], device_ids[0])


def save_warn_port(filename, device_id):

    sql = """SELECT d.zone_id ,z.name as zone_name ,d.factory_id,f.name as factory_name,
d.company_id,d.group_id,c.name as company_name,g.name as group_name ,g.proj_no
FROM device d
left JOIN regionlevel z on z.id = d.zone_id
LEFT JOIN regionlevel f on f.id = d.factory_id
LEFT JOIN regionlevel c on c.id = d.company_id
LEFT JOIN regionlevel g on g.id = d.group_id
WHERE d.id = """
    (
        zone_id,
        zone_name,
        factory_id,
        factory_name,
        company_id,
        group_id,
        company_name,
        group_name,
        proj_no,
    ) = db_fetchall(f"{sql}{device_id}")["data"][0]
    return db_insert(
        "report",
        {
            "title": filename,
            "maker": "系统生成",
            "result": "pdf文件内查看",
            "status": 1,
            "device_id": device_id,
            "zone_id": zone_id,
            "factory_id": factory_id,
            "company_id": company_id,
            "group_id": group_id,
            "filepath": filename + ".pdf",
            "type": 2,
        },
    )


def convert_date(input_date):
    # 将字符串转换为 datetime 对象
    date_obj = datetime.strptime(input_date, "%Y-%m-%d %H:%M:%S")
    # 格式化为指定的日期字符串
    formatted_date = date_obj.strftime("%Y年%m月%d日")
    return formatted_date


def categorize_data(input_list):
    output_dict = defaultdict(list)
    for item in input_list:
        feature_key = item["feature_key"]
        time = item["time"]
        value = item["value"]
        feature_key = feature_key[1:]
        output_dict[feature_key].append({"time": time, "value": value})
    return dict(output_dict)


def reduce_list_length(lst, target_length=8000):
    if len(lst) <= target_length:
        return lst
    # 确定步长
    step = len(lst) // target_length
    # 进行稀释
    new_lst = [lst[i] for i in range(0, len(lst), step)]
    return new_lst
